<template>
  <div class="face-recognition">
    <div class="toolbar">
      <div class="left-actions">
        <button class="action-btn primary" @click="showTrainingDialog = true">
          <i class="icon">📤</i>
          添加训练图片
        </button>
        <button class="action-btn" @click="showNewNameDialog = true">
          <i class="icon">📁</i>
          添加人名
        </button>
        <button class="action-btn" @click="showRecognizeDialog = true">
          <i class="icon">🔍</i>
          识别人脸
        </button>
      </div>
      <input 
        type="file" 
        ref="fileInput"
        accept="image/*"
        multiple
        @change="handleTrainingFileSelect"
        style="display: none"
      >
    </div>

    <div class="content-area">
      <!-- 左侧人名列表 -->
      <div class="categories-nav">
        <div class="nav-header">人名列表</div>
        <div class="nav-list">
          <div class="nav-item"
               :class="{ active: currentName === null }"
               @click="selectName(null)">
            <i class="icon">📁</i>
            <span class="item-name">未识别</span>
          </div>
          <div v-for="name in names"
               :key="name.id"
               class="nav-item"
               :class="{ active: currentName?.id === name.id }"
               @click="selectName(name)">
            <i class="icon">📁</i>
            <span class="item-name">{{ name.name }}</span>
            <button class="delete-btn" 
                    @click.stop="confirmDeleteName(name)"
                    title="删除人名">
              ❌
            </button>
          </div>
        </div>
      </div>

      <!-- 中间图片列表区域 -->
      <div class="image-list" v-if="currentName">
        <h3>{{ currentName.name }}的训练图片</h3>
        <div class="image-grid">
          <div v-for="image in nameImages" 
               :key="image.filename" 
               class="image-item">
            <div class="image-actions">
              <button class="delete-btn" 
                      @click.stop="confirmDeleteImage(image)"
                      title="删除图片">
                🗑️
              </button>
            </div>
            <img :src="`http://111.229.88.2:8000/uploads/${image.url}`" 
                 :alt="image.filename"
                 @error="handleImageError">
            <div class="image-info">
              <span class="filename">{{ image.filename }}</span>
              <span class="created-at">{{ formatDate(image.created_at) }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧结果显示区域 -->
      <div class="result-area">
        <div v-if="!faces.length" class="placeholder">
          请上传图片进行人脸识别
        </div>
        <div v-else>
          <h3>识别结果</h3>
          <div class="face-list">
            <div v-for="face in faces" 
                 :key="face.id" 
                 class="face-item"
                 :class="{ active: selectedFace?.id === face.id }"
                 @click="selectFace(face)">
              <div class="face-header">
                <span>{{ face.name || `人脸 ${face.id}` }}</span>
                <span class="confidence">置信度: {{ (face.confidence * 100).toFixed(1) }}%</span>
              </div>
              <div class="face-details">
                <p>年龄：{{ face.attributes?.age || '未知' }}</p>
                <p>性别：{{ face.attributes?.gender || '未知' }}</p>
                <p>表情：{{ face.attributes?.emotion || '未知' }}</p>
              </div>
              <div class="face-actions">
                <button class="action-btn" @click.stop="showUpdateNameDialog(face)">
                  修改人名
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 添加训练图片对话框 -->
    <div v-if="showTrainingDialog" class="dialog-overlay">
      <div class="dialog">
        <h3>添加训练图片</h3>
        <div class="form-item">
          <label>选择人名</label>
          <select v-model="selectedNameId">
            <option value="">请选择人名...</option>
            <option v-for="name in names" 
                    :key="name.id" 
                    :value="name.id">
              {{ name.name }}
            </option>
          </select>
        </div>
        <div class="form-item">
          <label>选择图片</label>
          <input type="file" 
                 ref="fileInput"
                 accept="image/*"
                 multiple
                 @change="handleTrainingFileSelect">
        </div>
        <div class="dialog-footer">
          <button class="cancel-btn" @click="showTrainingDialog = false">取消</button>
        </div>
      </div>
    </div>

    <!-- 添加人名对话框 -->
    <div v-if="showNewNameDialog" class="dialog-overlay">
      <div class="dialog">
        <h3>添加人名</h3>
        <div class="form-item">
          <label>姓名</label>
          <input 
            type="text" 
            v-model="newName"
            placeholder="请输入姓名"
          >
        </div>
        <div class="dialog-footer">
          <button class="cancel-btn" @click="showNewNameDialog = false">取消</button>
          <button class="confirm-btn" @click="createName">确定</button>
        </div>
      </div>
    </div>

    <!-- 修改人名对话框 -->
    <div v-if="showUpdateDialog" class="dialog-overlay">
      <div class="dialog">
        <h3>修改人名</h3>
        <div class="form-item">
          <label>选择人名</label>
          <select v-model="selectedUpdateNameId">
            <option value="">未识别</option>
            <option v-for="name in names" 
                    :key="name.id" 
                    :value="name.id">
              {{ name.name }}
            </option>
          </select>
        </div>
        <div class="dialog-footer">
          <button class="cancel-btn" @click="showUpdateDialog = false">取消</button>
          <button class="confirm-btn" @click="updateFaceName">确定</button>
        </div>
      </div>
    </div>

    <!-- 识别人脸对话框 -->
    <div v-if="showRecognizeDialog" class="dialog-overlay">
      <div class="dialog">
        <h3>识别人脸</h3>
        <div class="form-item">
          <label>选择图片</label>
          <input type="file" 
                 accept="image/*"
                 @change="handleRecognizeFileSelect">
        </div>
        <div class="dialog-footer">
          <button class="cancel-btn" @click="showRecognizeDialog = false">取消</button>
        </div>
      </div>
    </div>

    <ImageManager 
      type="face"
      :multiple="true"
      @upload-success="handleUploadSuccess"
      @upload-error="handleUploadError"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import axios from 'axios'


const fileInput = ref(null)
const faces = ref([])
const names = ref([])
const currentName = ref(null)
const selectedFace = ref(null)
const showNewNameDialog = ref(false)
const showTrainingDialog = ref(false)
const showRecognizeDialog = ref(false)
const newName = ref('')
const selectedNameId = ref('')
const selectedUpdateNameId = ref('')
const nameImages = ref([])

const triggerUpload = () => {
  fileInput.value?.click()
}

// 处理训练图片上传
const handleTrainingFileSelect = async (event) => {
  const files = event.target.files
  if (!files?.length) return
  
  const selectedName = names.value.find(n => n.id === parseInt(selectedNameId.value))
  if (!selectedName) {
    alert('请选择人名')
    return
  }
  
  const formData = new FormData()
  formData.append('file', files[0])
  
  try {
    const response = await axios.post(`http://111.229.88.2:8000/api/face-db/${String(selectedNameId.value)}`, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    showTrainingDialog.value = false
    alert('上传成功')
  } catch (err) {
    console.error('上传失败:', err)
    alert('上传失败: ' + (err.response?.data?.detail || err.message))
  }
}

// 处理识别图片上传
const handleRecognizeFileSelect = async (event) => {
  const files = event.target.files
  if (!files?.length) return
  
  const formData = new FormData()
  formData.append('file', files[0])
  
  try {
    const response = await axios.post('http://111.229.88.2:8000/api/recognize', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    showRecognizeDialog.value = false
    faces.value = response.data.faces.map((face, index) => ({
      ...face,
      id: index + 1
    }))
  } catch (err) {
    console.error('识别失败:', err)
    alert('识别失败: ' + (err.response?.data?.detail || err.message))
  }
}

// 选择人名
const selectName = async (name) => {
  currentName.value = name
  selectedFace.value = null
  
  if (name) {
    try {
      const response = await axios.get(`http://111.229.88.2:8000/api/face-db/${name.id}/images`, {
        headers: {
          'Authorization': `Bearer ${localStorage.getItem('token')}`
        }
      })
      nameImages.value = response.data
    } catch (err) {
      console.error('获取图片列表失败:', err)
      alert('获取图片列表失败')
    }
  } else {
    nameImages.value = []
  }
}

// 创建新人名
const createName = async () => {
  if (!newName.value) {
    alert('请输入姓名')
    return
  }
  
  try {
    const response = await axios.post('http://111.229.88.2:8000/api/face-names', {
      name: newName.value
    }, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    names.value.push(response.data)
    showNewNameDialog.value = false
    newName.value = ''
  } catch (err) {
    console.error('添加人名失败:', err)
    alert('添加人名失败')
  }
}

// 选择人脸
const selectFace = (face) => {
  selectedFace.value = face
}

// 显示更新人名对话框
const showUpdateNameDialog = (face) => {
  selectedFace.value = face
  selectedUpdateNameId.value = face.name_id || ''
  showUpdateDialog.value = true
}

// 更新人脸人名
const updateFaceName = async () => {
  if (!selectedFace.value) return
  
  try {
    await axios.put(`http://111.229.88.2:8000/api/faces/${selectedFace.value.id}/name`, {
      name_id: selectedUpdateNameId.value
    }, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    selectedFace.value.name_id = selectedUpdateNameId.value
    showUpdateDialog.value = false
  } catch (err) {
    console.error('更新人名失败:', err)
    alert('更新人名失败')
  }
}

// 确认删除人名
const confirmDeleteName = async (name) => {
  if (!confirm(`确定要删除人名 "${name.name}" 及其所有训练图片吗？`)) {
    return
  }
  
  try {
    await axios.delete(`http://111.229.88.2:8000/api/face-names/${name.id}`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    names.value = names.value.filter(n => n.id !== name.id)
    if (currentName.value?.id === name.id) {
      currentName.value = null
      nameImages.value = []
    }
  } catch (err) {
    console.error('删除人名失败:', err)
    alert('删除人名失败')
  }
}

// 格式化日期
const formatDate = (dateStr) => {
  const date = new Date(dateStr)
  return date.toLocaleString()
}

// 处理图片加载错误
const handleImageError = (event) => {
  event.target.src = ''  // 可以替换为一个默认的占位图片
}

// 确认删除图片
const confirmDeleteImage = async (image) => {
  if (!confirm(`确定要删除图片 "${image.filename}" 吗？`)) {
    return
  }
  
  try {
    // 从 URL 中提取文件名
    const filename = image.url.split('/').pop()
    await axios.delete(`http://111.229.88.2:8000/api/face-db/${currentName.value.id}/images/${filename}`, {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    
    // 从列表中移除已删除的图片
    nameImages.value = nameImages.value.filter(img => img !== image)
  } catch (err) {
    console.error('删除图片失败:', err)
    alert('删除图片失败: ' + (err.response?.data?.detail || err.message))
  }
}

onMounted(async () => {
  try {
    // 获取人名列表
    const response = await axios.get('http://111.229.88.2:8000/api/face-names', {
      headers: {
        'Authorization': `Bearer ${localStorage.getItem('token')}`
      }
    })
    names.value = response.data
  } catch (err) {
    console.error('获取人名列表失败:', err)
  }
})
</script>

<style scoped>
.face-recognition {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.toolbar {
  margin-bottom: 20px;
  padding: 16px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.left-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.action-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  background-color: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.action-btn:hover {
  background-color: #096dd9;
}

.icon {
  font-size: 18px;
}

.content-area {
  flex: 1;
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 20px;
  background: white;
  border-radius: 8px;
  overflow: hidden;
}

.categories-nav {
  padding: 20px;
  border-right: 1px solid #e8e8e8;
  background: #f8f8f8;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.nav-header {
  font-size: 16px;
  font-weight: bold;
  padding: 0 8px 16px;
  border-bottom: 1px solid #e8e8e8;
  margin-bottom: 16px;
}

.nav-item {
  padding: 8px;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  transition: all 0.3s;
}

.nav-item:hover {
  background: #f5f5f5;
}

.nav-item.active {
  background: #e6f7ff;
  color: #1890ff;
}

.image-list {
  padding: 20px;
  overflow: auto;
  background: white;
  height: 100%;
}

.image-list h3 {
  margin: 0 0 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid #e8e8e8;
}

.image-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
}

.image-item {
  background: white;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  position: relative;
  transition: transform 0.3s;
}

.image-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.image-item img {
  width: 100%;
  height: 180px;
  object-fit: cover;
}

.image-info {
  padding: 8px;
  font-size: 12px;
  color: #666;
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: rgba(255, 255, 255, 0.95);
}

.filename {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 500;
}

.created-at {
  color: #999;
  font-size: 11px;
}

.image-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.3s;
}

.image-item:hover .image-actions {
  opacity: 1;
}

.delete-btn {
  padding: 6px;
  background: rgba(255, 59, 48, 0.9);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 16px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.delete-btn:hover {
  background: rgba(255, 59, 48, 1);
  transform: scale(1.1);
}

.result-area {
  padding: 20px;
  background: #f8f8f8;
  border-left: 1px solid #e8e8e8;
  height: 100%;
  overflow: auto;
}

.result-area h3 {
  margin: 0 0 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid #e8e8e8;
}

.placeholder {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
}

.face-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.face-item {
  background: white;
  border-radius: 8px;
  padding: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s;
}

.face-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

.face-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.confidence {
  color: #1890ff;
  font-size: 14px;
}

.face-details p {
  margin: 8px 0;
  color: #666;
}

.face-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}

.action-btn {
  padding: 8px 16px;
  background-color: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.action-btn:hover {
  background-color: #096dd9;
}

.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.dialog {
  background-color: white;
  padding: 20px;
  border-radius: 8px;
  width: 400px;
}

.form-item {
  margin-bottom: 16px;
}

.form-item label {
  display: block;
  margin-bottom: 8px;
}

.form-item input,
.form-item select,
.form-item textarea {
  width: 100%;
  padding: 8px;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 16px;
}

.cancel-btn,
.confirm-btn {
  padding: 8px 16px;
  background-color: #1890ff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.3s;
}

.cancel-btn:hover,
.confirm-btn:hover {
  background-color: #096dd9;
}
</style>